package game;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

public class Tetris extends JPanel {
    BufferedImage bg;
    Tetromino tetromino;    //当前正在下落的四方格
    Tetromino nextOne;    //准备下落的四方格

    Timer loopTimer;    //下落计时器
    int lines = 0;
    int score = 0;
    int[] scoreTable = {0, 10, 25, 50, 100};    //0,1,2,3,4
    int interval = 600; //600毫秒 600毫秒下落一次
    Cell[][] wall = new Cell[20][10];   //墙
    final int ROWS = 20;    //格子墙高 常量 不可变
    final int COLS = 10;    //格子墙宽 常量 不可变
    final int CELL_SIZE = 26;   //每个小格子的宽高 常量 不可变
    static BufferedImage I; //静态的优先运行 比bg优先 可以通过类名.直接访问
    static BufferedImage J;
    static BufferedImage L;
    static BufferedImage O;
    static BufferedImage S;
    static BufferedImage T;
    static BufferedImage Z;

    static {    //静态块 方便读取
        try {    //尝试运行代码串，如果遇到错误把错误抓取并且打印下来  处理了异常代替抛异常
            I = ImageIO.read(new File("I.png")); // I图片
            J = ImageIO.read(new File("J.png")); // J图片
            L = ImageIO.read(new File("L.png")); // L图片
            O = ImageIO.read(new File("O.png")); // O图片
            S = ImageIO.read(new File("S.png")); // S图片
            T = ImageIO.read(new File("T.png")); // T图片
            Z = ImageIO.read(new File("Z.png")); // Z图片
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Tetris() throws Exception {    //构造器 抛异常
        bg = ImageIO.read(new File("tetris.png")); //图片读取风险异常
//        System.out.println(bg); 验证是否成功插入背景
        tetromino = Tetromino.randomOne();
        nextOne = Tetromino.randomOne();
    }

    //  游戏开始
    public void action() {
        //键盘监听器
        KeyAdapter ka = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();   //获取键盘按键编号
                if (key == KeyEvent.VK_Q) {
                    System.exit(0);
                }
                switch (key) {
                    case KeyEvent.VK_LEFT:
                        moveLeftAction();
                        break;
                    case KeyEvent.VK_RIGHT:
                        moveRightAction();
                        break;
                    case KeyEvent.VK_DOWN:
                        softDropAction();
                        break;
                    case KeyEvent.VK_SPACE:
                        hardDropAction();
                        break;
                    case KeyEvent.VK_UP:
                        rotateRightAction();
                        break;
                }
                repaint();  // 需要重画 否则画面卡顿
            }
        };
        this.addKeyListener(ka);  //为当前面板设置键盘监听
        this.setFocusable(true);    //设置焦点
        this.requestFocus();

        loopTimer = new Timer();    //  import java.util.Timer; 注意util包
        TimerTask tt = new TimerTask() {
            @Override
            public void run() {
                softDropAction();
                repaint();  //重画
            }
        };
        loopTimer.schedule(tt, 0, interval);  //计时器tt 从0开始执行 每600毫秒执行一次
    }

    //判断上下左右是否越界
    public boolean outOfBounds() {
        Cell[] cells = tetromino.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            if (row < 0 || row > 19 || col < 0 || col > 9) {
                return true;    //越界了
            }
        }
        return false;   //没有越界
    }

    //判断是否能继续下落（解决超出范围）
    public boolean canDrop() {
        //到底了不能落
        Cell[] cells = tetromino.cells;
        for (Cell cell : cells) {
            if (cell.getRow() == ROWS - 1) {
                return false;
            }
        }
        //以下有格子 不能落
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            if (wall[row + 1][col] != null) {
                return false;
            }
        }
        return true;

    }

    //游戏软下落（慢慢一格一格落）
    public void softDropAction() {
        if (canDrop()) {
            tetromino.softDrop();   //判断是否落
        } else {
            //不能下落 就上墙
            landIntoWall();
            int lines = destoryLines(); //0，1，2，3，4
            this.lines += lines;
            this.score += scoreTable[lines];
            tetromino = nextOne;
            nextOne = Tetromino.randomOne();
        }
    }

    //游戏硬下落（打回车直接落下来）
    public void hardDropAction() {
        while (canDrop()) {       //直接落
            tetromino.softDrop();
        }
        //不能下落 就上墙
        landIntoWall();
        int lines = destoryLines();
        this.lines += lines;
        this.score += scoreTable[lines];
        tetromino = nextOne;
        nextOne = Tetromino.randomOne();
    }

    //四方格上墙
    public void landIntoWall() {
        Cell[] cells = tetromino.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            wall[row][col] = cell;
        }
    }

    //判断某一行是否满行
    public boolean fullCells(int row) {
        Cell[] lines = wall[row];   //10个cell对象 或 空  wall[20][10]
        for (Cell cell : lines) {
            if (cell == null) {
                return false;
            }
        }
        return true;
    }

    //遍历所有行，查看都有哪一行是满行的
    public int destoryLines() {
        int lines = 0;
        for (int row = 0; row < 20; row++) {
            if (fullCells(row)) {
                //满了就删掉
                deleteLine(row);
                lines++;
            }
        }
        return lines;
    }

    //删除某一行
    public void deleteLine(int row) {
        for (int r = row; r > 0; r--) {
            System.arraycopy(wall[r - 1], 0, wall[r], 0, 10);
        }
        Arrays.fill(wall[0], null);
    }

    //判断左右重叠
    public boolean coincide() {
        Cell[] cells = tetromino.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            if (row >= 0 && row < ROWS && col >= 0 && col < COLS
                    && wall[row][col] != null) {
                return true;
            }
        }
        return false;
    }

    //游戏 左移动
    public void moveLeftAction() {
        tetromino.moveLeft();
        if (outOfBounds() || coincide()) {
            tetromino.moveRight();
        }
    }

    //游戏 右移动
    public void moveRightAction() {
        tetromino.moveRight();
        if (outOfBounds() || coincide()) {
            tetromino.moveLeft();
        }
    }

    //右旋转
    public void rotateRightAction() {
        tetromino.rotateRight();
        if (outOfBounds() || coincide()) {
            tetromino.rotateLeft(); //拉回 解决溢出

        }
    }

    @Override
    public void paint(Graphics g) {     //直接打paint
        g.drawImage(bg, 0, 0, null);
        //设置偏移量 15px
        g.translate(15, 15);
        paintWall(g);
        paintTetromino(g);
        paintNextOne(g);
        Font f = new Font(Font.SANS_SERIF, Font.BOLD, 30);
        g.setFont(f);
        g.setColor(Color.PINK);
        paintScore(g);
    }

    //画分数 行数
    public void paintScore(Graphics g) {
        int x = 290;
        int y = 160;
        g.drawString("Lines:" + lines, x, y);
        y += 55;
        g.drawString("Score:" + score, x, y);
    }

    //画即将下落的四方格
    public void paintNextOne(Graphics g) {
        Cell[] cells = nextOne.cells;
        for (Cell cell : cells) {
            int x = (cell.getCol() + 10) * CELL_SIZE;
            int y = (cell.getRow() + 1) * CELL_SIZE;
            g.drawImage(cell.getImage(), x, y, null);
        }
    }

    //画当前四方格
    public void paintTetromino(Graphics g) {
        Cell[] cells = tetromino.cells;
        for (Cell cell : cells) {
            int x = cell.getCol() * CELL_SIZE;
            int y = cell.getRow() * CELL_SIZE;
            g.drawImage(cell.getImage(), x, y, null);
        }
    }

    //画格子墙
    public void paintWall(Graphics g) {
        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                int x = col * CELL_SIZE;
                int y = row * CELL_SIZE;
                Cell c = wall[row][col];
                if (c == null) {
                    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);   //画空框
                } else {
                    g.drawImage(c.getImage(), x, y, null);
                }

            }
        }
    }


}
